#pragma once

#include <iostream>
#include <sys/select.h>
#include <sys/time.h>
#include <poll.h>
#include "Socket.hpp"

using namespace std;

static const uint16_t default_port = 8080;
static const int fd_num_max = 128;
int default_fd = -1;
int non_event = 0;

class Server
{
public:
    Server(uint16_t port = default_port)
    : _port(port)
    {
        //初始化“fd数组”
        for(int i=0; i<fd_num_max; i++)
        {
            _fd_array[i].fd = default_fd;
            _fd_array[i].events = non_event;
            _fd_array[i].revents = non_event;
        }
    }

    void Init()
    {
        _listen_sock.Socket();
        _listen_sock.Bind(_port);
        _listen_sock.Listen();
    }

    void Run()
    {
        //监听套接字加入fd数组
        _fd_array[0].fd = _listen_sock.Fd();
        //设置关心该fd的读事件
        _fd_array[0].events = POLLIN;

        int timeout = 3000;
        while(1)
        {
            //根据返回值做事，0等待超时，-1出错，其它表示有事件就绪
            int p = poll(_fd_array, fd_num_max, timeout);
            switch(p)
            {
            case 0:
                lg(Info, "timeout");
                break;
            case -1:
                lg(Error, "poll error");
                break;
            default:
                lg(Info, "event ready");
                EventReady();
            }
        }
    }

    void PrintFdArray()
    {
        cout << "fd_list: ";
        for(int i=0; i<fd_num_max; i++)
        {
            if(_fd_array[i].fd != default_fd)
            {
                cout << _fd_array[i].fd << " ";
            }
        }
        cout << endl;
    }

    ~Server()
    {
        _listen_sock.Close();
    }

private:
    void EventReady()
    {
        for(int i=0; i<fd_num_max; i++)
        {
            //遍历fd数组获取有效fd
            if(_fd_array[i].fd != default_fd)
            {
                //判断该fd的就绪事件中是否有读事件
                if(_fd_array[i].revents & POLLIN)
                {
                    //监听fd处理监听事件，其它fd处理读事件
                    if(_fd_array[i].fd == _listen_sock.Fd())
                    {
                        ListenEvent();
                    }
                    else
                    {
                        ReadEvent(_fd_array[i].fd, i);
                    }
                }
            }
        }
        
    }

    void ListenEvent()
    {
        //建立连接并获得新的fd
        string client_ip;
        uint16_t client_port;
        int accept_fd = _listen_sock.Accept(&client_ip, &client_port);
        if(accept_fd == -1)
            return;
        lg(Info, "accept success");

        //获取fd数组可用位置的下标
        int pos = 1;
        for(; pos<fd_num_max; pos++)
        {
            if(_fd_array[pos].fd == default_fd)
            {
                _fd_array[pos].fd = accept_fd;
                _fd_array[pos].events = POLLIN;
                _fd_array[pos].revents = non_event;
                PrintFdArray();
                break;
            }
        }
        //fd数组无可用位置
        if(pos == fd_num_max)
        {
            lg(Warning, "fd_array full");
            close(accept_fd);
        }
    }

    void ReadEvent(int fd, int pos)
    {
        char buffer[1024];
        int r = read(fd, buffer, sizeof(buffer)-1);
        if(r > 0)
        {
            buffer[r] = 0;
            cout << "get msg: " << buffer << endl;
        }
        else if(r == 0)
        {
            lg(Info, "client quit");
            close(fd);
            _fd_array[pos].fd = default_fd;
            _fd_array[pos].events = non_event;
            _fd_array[pos].revents = non_event;
        }
        else
        {
            lg(Error, "read err: %s[%d]", strerror(errno), errno);
            close(fd);
            _fd_array[pos].fd = default_fd;
            _fd_array[pos].events = non_event;
            _fd_array[pos].revents = non_event;
        }
    }

private:
    Sock _listen_sock; //监听套接字
    uint16_t _port; //端口
    struct pollfd _fd_array[fd_num_max]; //结构体数组，结构体维护fd
};